package ar.uba.is2.tr.conf;

import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import ar.uba.is2.common.mensaje.Componente;
import ar.uba.is2.common.mensaje.Receptor;
import ar.uba.is2.common.mensaje.canal.Canal;
import ar.uba.is2.common.mensaje.canal.impl.CanalImpl;
import ar.uba.is2.common.mensaje.filtro.impl.FiltroDesordenaMensaje;
import ar.uba.is2.common.mensaje.filtro.impl.FiltroPierdeMensajes;
import ar.uba.is2.common.mensaje.protocolo.Protocolo;
import ar.uba.is2.common.mensaje.protocolo.impl.SterenProtocol;
import ar.uba.is2.common.mensaje.puerto.impl.PuertoArchivoFactory;
import ar.uba.is2.common.threads.ThreadManager;
import ar.uba.is2.tr.dispatcher.ModuloComunicacionSimple;
import ar.uba.is2.tr.dispatcher.TerminalRemotaDispatcher;
import ar.uba.is2.tr.impl.MensajeriaEcImpl;
import ar.uba.is2.tr.sensor.SensorMock;

public class Configuracion {
	
	private static final String archivoConfiguracion = "tr.properties";

	public Contexto iniciar() {

		crearContexto();
		
		configuracionGral();

		TerminalRemotaDispatcher dispatcher = new TerminalRemotaDispatcher(Contexto.instance.getComponenteTerminalRemotaLocal());

		configurarModuloComunicacion(Contexto.instance.getComponenteTerminalRemotaLocal(), dispatcher);
		
		return Contexto.instance;
	}
	
	private void configuracionGral() {
		String nombreTr = Contexto.instance.get("tr.nombre");
		String nombreEc = Contexto.instance.get("tr.nombreEc");
		
		Componente componenteTR = crearComponente(nombreTr);
		Componente componenteEC = crearComponente(nombreEc);

		Contexto.instance.setComponenteEstacionCentral(componenteEC);
		Contexto.instance.setComponenteTerminalRemotaLocal(componenteTR);
		
		String stringSensores = Contexto.instance.get(String.format("tr.%s.sensores",nombreTr));
		
		List<String> list = Arrays.asList(stringSensores.split(","));
		
		crearSensores(list);
		
	}

	private void configurarModuloComunicacion(Componente componenteTR,
			TerminalRemotaDispatcher dispatcher) {

		ModuloComunicacionSimple moduloComunicacion = new ModuloComunicacionSimple();
		Protocolo protocolo = configurarProtocolo(componenteTR, dispatcher);
		moduloComunicacion.setProtocolo(protocolo);	
		MensajeriaEcImpl mensajeriaEC = new MensajeriaEcImpl();
		

		Contexto.instance.setModuloComunicacion(moduloComunicacion);
		
		ThreadManager.instance.crearYCorrerThread(mensajeriaEC);
	}

	private Protocolo configurarProtocolo(Componente componenteTR, Receptor trDispatcher) {
		long retryTime = Long.parseLong(Contexto.instance.get("tr.protocolo.steren.msg.retry"));
		long timeout = Long.parseLong(Contexto.instance.get("tr.protocolo.steren.msg.timeout"));
		SterenProtocol protocol = new SterenProtocol(trDispatcher, retryTime, timeout);
		
		Canal canalDeComunicacion = crearCanal(componenteTR, protocol);
		
		protocol.setCanal(canalDeComunicacion);
		
		return protocol;
	}

	private Canal crearCanal(Componente componenteTR, Receptor receptor) {
		CanalImpl canal = new CanalImpl();
		canal.setPuertoFactory(new PuertoArchivoFactory("TR"));
		canal.suscribirEntrada(componenteTR, receptor);
		canal.suscribirSalida(Contexto.instance.getComponenteEstacionCentral());

		if(Boolean.parseBoolean(Contexto.instance.get("tr.canal.filtro.pierde.mensajes"))){
			canal.suscribirFiltro(new FiltroPierdeMensajes());
		}
		if(Boolean.parseBoolean(Contexto.instance.get("tr.canal.filtro.desordena.mensajes"))){
			canal.suscribirFiltro(new FiltroDesordenaMensaje());
		}
		
		return canal;
	}

	private Componente crearComponente(String nombreComponente) {
		 return new Componente(nombreComponente);
	}

	private void crearContexto() {
		Contexto contexto = new Contexto();
		Contexto.instance = contexto;
		
		Properties propiedades = new Properties();
		try {
			propiedades.load(ClassLoader.getSystemResourceAsStream(archivoConfiguracion));
		} catch (IOException e) {
			e.printStackTrace();
		}		
		Contexto.instance.setPropiedades(propiedades);

	}

	private void crearSensores(List<String> list) {
		for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
			int id = Integer.parseInt(((String) iterator.next()));
			
			long frecuencia = Long.parseLong(Contexto.instance.get(String.format("sensor.%s.frecuencia", id)));
			new SensorMock(id, frecuencia);	
		}
	}

}
